#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using C4F.DevKit.Telephony;
using System.Threading;
using System.IO;
using System.Diagnostics;
#endregion

namespace TapiSampleApplication
{
    public partial class frmTelephony : Form
    {
        #region Globals

        TapiManager tapiManager;
        int fileRecordCount = 1;
        bool autoAnsweringOptionSelected = false;
        bool listenVoiceMailsOptionSelected = false;
        bool voiceMailPlaybackStarted = false;
        string userPassword = String.Empty;
        public delegate void ChangeStateDelegate(object stateObject);
        public delegate void ChangeTabState();
        TapiCallEventLog callEventLog = null;
        Settings settings = new Settings(Environment.CurrentDirectory + "\\");

        #endregion

        #region Properties

        public TapiManager TapiManager
        {
            get
            {
                return tapiManager;
            }
            set
            {
                tapiManager = value;
            }
        }

        #endregion

        #region Constructors

        public frmTelephony()
        {
            InitializeComponent();
            tapiManager = tapiManager1;
            tapiManager.OnIncomingCall += new TapiManager.CallNotificationEventHandler(tapiManager_OnIncomingCall);
            tapiManager.OnCallConnected += new TapiManager.CallNotificationEventHandler(tapiManager_OnCallConnected);
            tapiManager.OnCallDisconnected += new TapiManager.CallNotificationEventHandler(tapiManager_OnCallDisconnected);
            tapiManager.OnOutgoingCall += new TapiManager.CallNotificationEventHandler(tapiManager_OnOutgoingCall);
            tapiManager.OnCallHold += new TapiManager.CallNotificationEventHandler(tapiManager_OnCallHold);
            tapiManager.OnDigitReceived += new TapiManager.DigitNotificationEventHandler(tapiManager_OnDigitReceived);
            tapiManager.OnEndOfFilePlayback += new TapiManager.EndOfPlaybackNotificationEventHandler(tapiManager_OnEndOfFilePlayback);

            dialPanel1.TapiManager = tapiManager;
            dtmfPanel1.TapiManager = tapiManager;
            playbackAndRecordingPanel1.TapiManager = tapiManager;
        }

        #endregion

        #region Tapi Event Handlers

        private void tapiManager_OnIncomingCall(CallInfo call)
        {
            // Log Entry For Call.
            LogEntry(call);
            
            // Check auto answering of incoming call.
            if (chkAutoAnswering.Checked == true)
            {
                try
                {
                    tapiManager.AnswerCall();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            // Display Incoming call form to handle incoming call if auto answering is not enabled.
            else
            {
                try
                {
                    if (DialogResult.Yes == MessageBox.Show("Answer call", "Incoming call", MessageBoxButtons.YesNo))
                    {
                        tapiManager.AnswerCall(call);
                    }
                }
                catch (Exception exception)
                {
                    MessageBox.Show(exception.Message, "Telephony Application", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void tapiManager_OnCallConnected(CallInfo call)
        {
            // Log Entry For Call.
            LogEntry(call);

            // Check auto answering of incoming call.
            if (chkAutoAnswering.Checked == true)
            {
                try
                {
                    tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\Welcome.wav");
                    // Welcome message time.
                    Thread.Sleep(12000);
                    tapiManager.StopPlayingFile();
                    tapiManager.StartDigitDetection();
                }
                catch (Exception exception)
                {
                    MessageBox.Show(exception.Message, "Telephony Application", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                ChangeStateDelegate del = new ChangeStateDelegate(EnableDialOptionsButtons);
                ChangeStateDelegate del1 = new ChangeStateDelegate(EnableResumeButton);
                ChangeStateDelegate del2 = new ChangeStateDelegate(EnableHoldButton);
                ChangeTabState del3 = new ChangeTabState(EnablingTabs);
                if (tbAnsweringMachine.InvokeRequired)
                {
                    tbAnsweringMachine.Invoke(del, false);
                    tbAnsweringMachine.Invoke(del1, false);
                    tbAnsweringMachine.Invoke(del2, true);
                    tbAnsweringMachine.Invoke(del3);
                }
            }
        }

        private void tapiManager_OnCallDisconnected(CallInfo call)
        {
            // Log Entry For Call.
            LogEntry(call);
            
            autoAnsweringOptionSelected = false;
            listenVoiceMailsOptionSelected = false;
            voiceMailPlaybackStarted = false;
            ChangeStateDelegate del1 = new ChangeStateDelegate(EnableDialOptionsButtons);
            ChangeStateDelegate del2 = new ChangeStateDelegate(EnableHoldButton);
            ChangeStateDelegate del3 = new ChangeStateDelegate(EnableDtmf);
            ChangeStateDelegate del4 = new ChangeStateDelegate(EnablePlayback);
            if (Dial.InvokeRequired)
            {
                Dial.Invoke(del1, true);
                Dial.Invoke(del2, false);
                Dial.Invoke(del3, false);
                Dial.Invoke(del4, false);
            }
        }

        private void tapiManager_OnOutgoingCall(CallInfo call)
        {
            // Log Entry For Call.
            LogEntry(call);
        }

        private void tapiManager_OnCallHold(CallInfo call)
        {
            // Log Entry For Call.
            LogEntry(call);
            
            ChangeStateDelegate del1 = new ChangeStateDelegate(EnableResumeButton);
            ChangeStateDelegate del2 = new ChangeStateDelegate(EnableHoldButton);
            if (Dial.InvokeRequired)
            {
                Dial.Invoke(del1, true);
                Dial.Invoke(del2, false);
            }
        }

        private void tapiManager_OnDigitReceived(CallInfo call, char digit)
        {
            // Log Entry For Call.
            LogEntry(call, "Digit Received : " + digit.ToString());

            try
            {
                #region Auto-answering enabled

                if (chkAutoAnswering.Checked == true)
                {
                    #region Password Verification and Listen Voice Mails

                    if (listenVoiceMailsOptionSelected == true && userPassword.Length < 4)
                    {
                        // Collect password.
                        userPassword += digit.ToString();
                        if (userPassword.Length == 4)
                        {
                            listenVoiceMailsOptionSelected = false;
                            // Perform password validation.
                            // 4 digit password(Sample passowrd: 1234).
                            tapiManager.StopDigitDetection();
                            if (userPassword.Equals("1234"))
                            {
                                if (!Directory.Exists(Environment.CurrentDirectory + "\\VoiceMails"))
                                {
                                    Directory.CreateDirectory(Environment.CurrentDirectory + "\\VoiceMails");
                                }
                                string[] voiceMails = Directory.GetFiles("VoiceMails", "CallRecord*.wav");
                                if (voiceMails.Length == 0)
                                {
                                    tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\NoVoiceMails.wav");
                                    // Message time.
                                    Thread.Sleep(6000);
                                    tapiManager.DisconnectCall();
                                    autoAnsweringOptionSelected = false;
                                    return;
                                }
                                else
                                {
                                    List<string> voiceMailsPaths = new List<string>(voiceMails);
                                    voiceMailsPaths.Add(Environment.CurrentDirectory + "\\..\\..\\Resources\\ThankYou.wav");
                                    tapiManager.PlayFiles(voiceMailsPaths);
                                    voiceMailPlaybackStarted = true;
                                    autoAnsweringOptionSelected = false;
                                    tapiManager.StartDigitDetection();
                                    return;
                                }
                            }
                            else
                            {
                                tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\InvalidPassword.wav");
                                // Message time.
                                Thread.Sleep(3000);
                                tapiManager.DisconnectCall();
                                autoAnsweringOptionSelected = false;
                                return;
                            }

                        }
                        else
                        {
                            return;
                        }
                    }

                    #endregion

                    #region Save Voice Message

                    if (digit == '1' && autoAnsweringOptionSelected == false)
                    {
                        autoAnsweringOptionSelected = true;
                        tapiManager.StopDigitDetection();

                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\LeaveMessage.wav");
                        // Message time.
                        Thread.Sleep(3500);
                        tapiManager.StopPlayingFile();

                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\Beep.wav");
                        // Message time.
                        Thread.Sleep(1000);
                        tapiManager.StopPlayingFile();

                        if (!Directory.Exists(Environment.CurrentDirectory + "\\VoiceMails"))
                        {
                            Directory.CreateDirectory(Environment.CurrentDirectory + "\\VoiceMails");
                        }
                        string[] voiceMails = Directory.GetFiles("VoiceMails", "CallRecord*.wav");
                        fileRecordCount = voiceMails.Length + 1;
                        // Start recording.
                        tapiManager.RecordCall(Environment.CurrentDirectory + "\\VoiceMails\\CallRecord" + fileRecordCount.ToString() + ".wav");

                        // Recording time.
                        Thread.Sleep(15000);
                        // Stop Recording.
                        tapiManager.StopCallRecording();
                        fileRecordCount++;

                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\Beep.wav");
                        // Message time.
                        Thread.Sleep(1000);
                        tapiManager.StopPlayingFile();

                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\ThankYou.wav");
                        // Message time.
                        Thread.Sleep(2000);
                        tapiManager.DisconnectCall();
                        autoAnsweringOptionSelected = false;
                        return;
                    }

                    #endregion

                    #region Password Input

                    else if (digit == '2' && autoAnsweringOptionSelected == false)
                    {
                        listenVoiceMailsOptionSelected = true;
                        userPassword = String.Empty;
                        autoAnsweringOptionSelected = true;

                        tapiManager.StartDigitDetection();
                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\Password.wav");
                        // Message time.
                        Thread.Sleep(3000);
                        tapiManager.StopPlayingFile();
                        return;
                    }

                    #endregion

                    #region Delete Voice Mails

                    else if (digit == '3' && autoAnsweringOptionSelected == false)
                    {
                        autoAnsweringOptionSelected = true;
                        tapiManager.StopDigitDetection();
                        string voiceMailDirectory = Environment.CurrentDirectory + "\\VoiceMails";
                        if(Directory.Exists(voiceMailDirectory))
                        {
                            string[] voiceMails = Directory.GetFiles(Environment.CurrentDirectory + "\\VoiceMails");
                            foreach (string voiceMail in voiceMails)
                            {
                                File.Delete(voiceMail);
                            }
                            tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\DeleteVoiceMails.wav");
                            Thread.Sleep(5000);
                        }
                        tapiManager.DisconnectCall();
                        autoAnsweringOptionSelected = false;
                    }

                    #endregion

                    #region Exit System

                    else if (digit == '0' && autoAnsweringOptionSelected == false)
                    {
                        autoAnsweringOptionSelected = true;
                        tapiManager.StopDigitDetection();
                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\ThankYou.wav");
                        // Message time.
                        Thread.Sleep(3000);
                        tapiManager.DisconnectCall();
                        autoAnsweringOptionSelected = false;
                    }

                    #endregion

                    #region Invalid Option

                    else
                    {
                        autoAnsweringOptionSelected = true;
                        tapiManager.StopDigitDetection();
                        tapiManager.PlayFile(Environment.CurrentDirectory + "\\..\\..\\Resources\\WrongChoice.wav");
                        // Message time.
                        Thread.Sleep(5000);
                        tapiManager.DisconnectCall();
                        autoAnsweringOptionSelected = false;
                    }

                    #endregion

                    return;
                }

                #endregion

                #region DTMF operation

                else
                {
                    ChangeStateDelegate del1 = new ChangeStateDelegate(DigitDetectionTextBoxUpdate);
                    if (DTMF.InvokeRequired)
                    {
                        DTMF.Invoke(del1, digit);
                    }
                }

                #endregion
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message, "Telephony Application", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void tapiManager_OnEndOfFilePlayback(CallInfo call)
        {
            // Log Entry For Call.
            LogEntry(call);

            if (voiceMailPlaybackStarted == true && call.CallState == CallState.Connected)
            {
                tapiManager.DisconnectCall();
            }

            
        }

        private void LogEntry(CallInfo call, string category)
        {
            try
            {
                if (chkBoxCallLog.Checked)
                {
                    Trace.Write(call, category);
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        private void LogEntry(CallInfo call)
        {
            try
            {
                if (chkBoxCallLog.Checked)
                {
                    Trace.Write(call);
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        #endregion

        #region Helper Methods

        private void EnableDialOptionsButtons(object stateObject)
        {
            dialPanel1.DialOptionsButtonsEnabled = (bool) stateObject;
        }

        private void EnableHoldButton(object stateObject)
        {
            dialPanel1.HoldButtonEnabled = (bool) stateObject;     
        }

        private void EnableResumeButton(object stateObject)
        {
            dialPanel1.ResumeButtonEnabled = (bool) stateObject;
        }

        private void EnableDtmf(object stateObject)
        {
            dtmfPanel1.DtmfEnabled = (bool) stateObject;
        }

        private void EnablePlayback(object stateObject)
        {
            playbackAndRecordingPanel1.PlaybackEnabled = (bool) stateObject;
        }

        private void EnablePlayStopButtons(bool state)
        {
            playbackAndRecordingPanel1.PlayStopButtonsEnabled = (bool) state;
        }

        private void EnablePlayBackControls(bool state)
        {
            playbackAndRecordingPanel1.PlayBackControlsEnabled = (bool) state;
        }

        private void EnableCallRecordingControls(bool state)
        {
            playbackAndRecordingPanel1.CallRecordingControlsEnabled = (bool) state;
        }

        private void EnablingTabs()
        {
            if (tapiManager.CurrentCall == null)
            {
                dtmfPanel1.DtmfEnabled = false;
                playbackAndRecordingPanel1.PlaybackEnabled = false;
            }
            else
            {
                dtmfPanel1.DtmfEnabled = true;
                playbackAndRecordingPanel1.PlaybackEnabled = true;
            }
        }

        private void DigitDetectionTextBoxUpdate(object digitObject)
        {
            dtmfPanel1.DigitDetectionTextBoxUpdate(digitObject);
        }

        private void ChangeStateOfClearButton()
        {
            dtmfPanel1.ChangeStateOfClearButton();
        }

        #endregion

        #region Event Handlers

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void tbAnsweringMachine_SelectedIndexChanged(object sender, EventArgs e)
        {
            EnablingTabs();
        }

        private void frmTelephony_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                tapiManager.TapiShutdown();
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message, "Telephony Application", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void chkAutoAnswering_CheckedChanged(object sender, EventArgs e)
        {
            if (chkAutoAnswering.Checked == true)
            {
                // Disable the whole tab contol. 
                tbAnsweringMachine.Enabled = false;
            }
            else
            {
                // Enable the whole tab contol. 
                tbAnsweringMachine.Enabled = true;
            }
        }

        private void chkBoxCallLog_CheckedChanged(object sender, EventArgs e)
        {
            if (chkBoxCallLog.Checked == true)
            {
                // Telephony log listener added. 
                AddTraceListener();                                      
            }
            if (chkBoxCallLog.Checked == false)
            {
                Trace.Listeners.Remove(callEventLog);
            }
        }

        internal void AddTraceListener()
        {
            callEventLog = new TapiCallEventLog(settings.GetLogFileName());
            Trace.Listeners.Add(callEventLog);
        }

        private void btnSettings_Click(object sender, EventArgs e)
        {
            settings.ShowDialog();
            Trace.Listeners.Remove(callEventLog);
            AddTraceListener();
        }

        #endregion
    }
}
